package cn.cas.mango.service;

import cn.cas.mango.dto.Message;
import cn.cas.mango.dto.News;
import cn.cas.mango.dto.param.BaseParam;
import cn.cas.mango.dto.param.QueryParam;
import cn.cas.mango.dto.param.TopicParam;
import cn.cas.mango.util.RequestUtil.BuildRequest;
import cn.cas.mango.util.ResponseUtil.ResponseUtil;
import cn.cas.mango.util.paramCheck.QueryParamCheckUtil;
import cn.cas.mango.util.paramCheck.TopicParamCheckUtil;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.SortOptions;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.Hit;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@Slf4j
public class TopicService {
@Autowired
private ElasticsearchClient elasticsearchClient;
  @Autowired
  private ConfigService config;
  @Autowired
  private BuildRequest buildRequest;
  public Message run(BaseParam baseParam) {
    TopicParam topicParam = (TopicParam) baseParam;
    Map<String, Object> errMessage = TopicParamCheckUtil.checkParam(topicParam);
    String isSuccess = (String) errMessage.get("isSuccess");
    if (!isSuccess.equals("ok")) {
      return Message.unSuccess(isSuccess);
    }
    MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
    requestBody.add("query", "您的查询字符串");

    RestTemplate restTemplate = new RestTemplateBuilder().build();
    String url = "http://" + config.getOuterAddress() + "/ReadingAssist/special/getTopicInfo";

    // Create a map for the parameters
    MultiValueMap<String, String> paramMap = new LinkedMultiValueMap<>();
    paramMap.add("id", topicParam.getTopicNm());

    // Create the http headers and set the content type to form-urlencoded
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

    // Create the HttpEntity containing the form parameters
    HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(paramMap, headers);

    // Send the request as a POST method
//    ResponseEntity<JSONObject> responseEntity = restTemplate.postForEntity(url, request, JSONObject.class);


    url = url + String.format("?id=%s", topicParam.getTopicNm());
    ResponseEntity<JSONObject> responseEntity = restTemplate.getForEntity(url, JSONObject.class);
    JSONObject responseJson = Objects.requireNonNull(responseEntity.getBody());
    //    if ((Integer) responseJson.get("code") != 200) {
//      return Message.unSuccess("查询关键词失败");
//    }
    List<String> keywords = new ArrayList<>();
    log.info("response data: {}", responseJson);
    JSONObject data = responseJson.getJSONObject("data");

    JSONArray jsonArray = data.getJSONArray("keywords");
    keywords.addAll(jsonArray.stream().map(x->(String)x).collect(Collectors.toList()));
    QueryParam queryParam = wrapQueryParam(topicParam);
    queryParam.setQueryStr(String.join(" ", keywords));

    SortOptions sortOptions1 = (SortOptions) queryParam.get3Sorts().get(2);

    SortOptions sortOptions2 = SortOptions.of(
        s -> s.field(f -> f.field("_score").order(SortOrder.Desc)));

    SearchRequest.Builder requestBuilder =  buildRequest.buildRequest(queryParam).sort(new ArrayList<SortOptions>(){{add(sortOptions1);add(sortOptions2);}});;
    SearchResponse<News> search;

    JSONObject sim = new JSONObject();

    try {
      SearchRequest build = requestBuilder.build();
      search = elasticsearchClient.search(build, News.class);
      log.info("query str: {}", build);
      sim.put("total", search.hits().total().value());
      List<JSONObject> list = new ArrayList<>();
      List<Hit<News>> hits = search.hits().hits();
      for (Hit<News> hit: hits) {
        News source = hit.source();
        JSONObject newsLink = new JSONObject();
        Map<String, List<String>> highlight = hit.highlight();
        ResponseUtil.putTitleContent(highlight, newsLink, source, true);
        ResponseUtil.putCommon(config, newsLink, hit);
        newsLink.put("news_website_type", source.getNewsWebsiteType());
        newsLink.put("news_publictime_date", source.getNewsPublicTime());
        newsLink.put("news_publictime", source.getNewsPublicTime());
        newsLink.put("marked", false);
        newsLink.put("numOfComments", 0);
        newsLink.put("score", hit.score());
        list.add(newsLink);
      }
      sim.put("documents", list);

    } catch (IOException e) {
      throw new RuntimeException(e);
    }
    return Message.builder().data(sim).message("success").code(200).build();

  }

  private QueryParam wrapQueryParam(TopicParam topicParam) {
    QueryParam queryParam = new QueryParam();
    queryParam.setCurrentPage(topicParam.getCurrentPage());
    queryParam.setPageSize(topicParam.getPageSize());
    queryParam.setStartDate(topicParam.getStartDate());
    queryParam.setEndDate(topicParam.getEndDate());
    queryParam.setWebSiteType(topicParam.getSource());
    queryParam.setSortType(topicParam.getOrder());
    queryParam.setLikeDegree(config.getTopicLikeDegree());
    queryParam.setSearchType("false");
    QueryParamCheckUtil.checkParam(queryParam, queryParam.getPageSize());
    return queryParam;
  }

  }
